import pymysql
import random

MAX_SCORE = 100
MIN_SCORE = 0
INITIAL_SCORE = 10
MYSQL_HOSTS = '47.101.51.103'
MYSQL_PORT = 3306
MYSQL_USER = 'root'
MYSQL_PASSWORD = '1qaz@WSX'
MYSQL_DB = 'proxy'

cnx = None
cur = None


class MysqlClient(object):
    def __init__(self):
        self.cnx = pymysql.connect(host=MYSQL_HOSTS, port=MYSQL_PORT, user=MYSQL_USER, passwd=MYSQL_PASSWORD,
                                   db=MYSQL_DB)
        self.cur = self.cnx.cursor()

    def add_award(self, name):
        sql = 'INSERT INTO db_award(name) values ("{}")'.format(name)
        print(sql)
        self.cur.execute(sql)
        self.cnx.commit()

    def add(self, proxy, tag, score=INITIAL_SCORE):
        if not self.has_same(proxy):
            sql = 'INSERT INTO db_proxy(address,tag,score) values ("{}","{}","{}")'.format(proxy, tag, score)
            print(sql)
            self.cur.execute(sql)
            self.cnx.commit()

    # 添加代理
    def has_same(self, proxy):
        sql = 'SELECT * FROM db_proxy where address= "{}"'.format(proxy)
        self.cur.execute(sql)
        proxy_list = self.cur.fetchall()
        if len(proxy_list) > 0:
            return True
        else:
            return False

    def random_proxy(self):
        # 随机获取代理，先尝试获取最高分数代理
        sql = "SELECT * FROM db_proxy where score =100 "  # AND tag='高匿'
        self.cur.execute(sql)
        proxy_list = self.cur.fetchall()
        if len(proxy_list) > 0:
            index = random.randint(0, len(proxy_list) - 1)
            address = proxy_list[index][1]
            return address
        else:
            return None

    def delete_proxy(self):
        sql = 'DELETE  FROM db_proxy where score<0'
        self.cur.execute(sql)
        self.cnx.commit()

    def decrease(self, proxy):
        sql = 'UPDATE db_proxy set score=score-1 where address="{}"'.format(proxy)
        self.cur.execute(sql)
        self.cnx.commit()

    def increase(self, proxy):
        sql = 'UPDATE db_proxy set score=100 where address="{}"'.format(proxy)
        self.cur.execute(sql)
        self.cnx.commit()

    def get_all(self):
        sql = 'SELECT * FROM db_proxy'
        self.cur.execute(sql)
        proxy_list = self.cur.fetchall()
        address_list = []
        for proxy in proxy_list:
            address_list.append(proxy[1])
        return address_list


import aiohttp
import asyncio
import time

VALID_STATUS_CODE = [200]
TEST_URL = 'https://url.cn/5proFc8'
BATCH_TEST_SIZE = 100


class TestProxy(object):
    def __init__(self):
        self.mysql = MysqlClient()

    async def test_single_proxy(self, proxy):
        conn = aiohttp.TCPConnector(verify_ssl=False)
        async with aiohttp.ClientSession(connector=conn) as session:
            try:
                if isinstance(proxy, bytes):
                    proxy = proxy.decode('utf-8')
                real_proxy = 'http://' + proxy
                print('正在测试', proxy)
                async with session.get(TEST_URL, proxy=real_proxy, timeout=15) as response:
                    if response.status in VALID_STATUS_CODE:
                        self.mysql.increase(proxy)
                        print('代理可用', proxy)
                    else:
                        self.mysql.decrease(proxy)
                        print('代理不可用', proxy)
            except(TimeoutError, AttributeError, Exception):
                self.mysql.decrease(proxy)
                print('代理请求失败')

    def run(self):
        print("删除垃圾ip----")
        self.mysql.delete_proxy()
        print("测试开始运行")
        try:
            proxies = self.mysql.get_all()
            loop = asyncio.get_event_loop()
            for i in range(0, len(proxies), BATCH_TEST_SIZE):
                test_proxies = proxies[i:i + BATCH_TEST_SIZE]
                tasks = [self.test_single_proxy(proxy) for proxy in test_proxies]
                loop.run_until_complete(asyncio.wait(tasks))
                time.sleep(5)
        except Exception as e:
            print("测试发生错误，", e)


if __name__ == '__main__':
    test = TestProxy()
    test.run()
